package com.imay.live.heartlikeslib.hearthikesview;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PathMeasure;
import android.graphics.Rect;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;

import com.imay.live.heartlikeslib.R;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

/**
 * Created by kince on 16-8-2.
 */
public class HeartLikeView extends View {

    //private Bitmap mBitmap;// 当前显示的图像
    private ArrayList<Integer> totalBitmaps;// 一共有几种图像

    private List<PathObj> list = new ArrayList<>();// 路径

    private Random mRandom = new Random();
    private boolean mFlag;//
    private long mStartTime = 0;

    private int type;

    private Context mContext;

    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(android.os.Message msg) {
            int what = msg.what;
            switch (what) {
                case 0:
                    list.add(new PathObj(createHeart(), 0, 0));
                    mFlag = true;
                    this.post(mRunnable);
                    break;
                default:
                    break;
            }
        }
    };

    private Runnable mRunnable = new Runnable() {
        @Override
        public void run() {
            invalidate();
        }
    };
    private float mStartX;
    private float mStartY;

    public HeartLikeView(Context context) {
        this(context, null);
    }

    public HeartLikeView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public HeartLikeView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        TypedArray arr = context.obtainStyledAttributes(attrs, R.styleable.HeartLikeView, 0, 0);
        if (attrs != null) {
            if (arr.hasValue(R.styleable.HeartLikeView_type)) {
                type = arr.getInt(R.styleable.HeartLikeView_type, 0);
            }
            arr.recycle();
        }
        init(context);
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        if (mFlag) {
            release();
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        if (list == null) {
            return;
        }
        if (mFlag) {
            drawView(canvas);
            this.post(mRunnable);
        }
    }

    private void init(Context context) {
        totalBitmaps = new ArrayList<>();
        if (type == 0) {
            totalBitmaps.add(R.mipmap.dianzan1);
            totalBitmaps.add(R.mipmap.dianzan2);
            totalBitmaps.add(R.mipmap.dianzan3);
            totalBitmaps.add(R.mipmap.dianzan4);
            totalBitmaps.add(R.mipmap.dianzan5);
            totalBitmaps.add(R.mipmap.dianzan6);
            totalBitmaps.add(R.mipmap.dianzan7);
            totalBitmaps.add(R.mipmap.dianzan8);
            totalBitmaps.add(R.mipmap.dianzan9);
            totalBitmaps.add(R.mipmap.dianzan10);
            totalBitmaps.add(R.mipmap.dianzan11);
            totalBitmaps.add(R.mipmap.dianzan12);
        } else if (type == 1) {
            totalBitmaps.add(R.mipmap.btn_yinfu1);
            totalBitmaps.add(R.mipmap.btn_yinfu2);
        }

        mContext = context;
    }

    public boolean isRunning() {
        return mFlag;
    }

    /**
     * 绘图图像
     */
    public void drawView(Canvas canvas) {
        try {
            drawPath(canvas);
        } catch (Exception e) {
        }
    }

    private int randomColor() {
        return Color.rgb(mRandom.nextInt(255), mRandom.nextInt(255), mRandom.nextInt(255));
    }

    public Bitmap createHeart() {
        int i = mRandom.nextInt(totalBitmaps.size());
        Bitmap bm = BitmapFactory.decodeResource(getResources(), totalBitmaps.get(i));
        // 定义矩阵对象
        Matrix matrix = new Matrix();
        // 缩放原图
        matrix.postScale(2f, 2f);

        Bitmap bitmap = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(), bm.getHeight(),
                matrix, true);
        bm.recycle();
        return bitmap;
    }

    /**
     * 绘制贝赛尔曲线
     *
     * @param canvas 主画布
     */
    public void drawPath(Canvas canvas) {
        if (list.size() <= 0) {
            mFlag = false;
        }
        for (int i = 0; i < list.size(); i++) {
            try {
                PathObj obj = list.get(i);
                if (obj.getAlpha() <= 0) {
                    list.remove(i);
                    i--;
                    continue;
                }
                Rect src = obj.getSrcRect();
                Rect dst = obj.getDstRect();
                if (dst == null) {
                    list.remove(i);
                    i--;
                    continue;
                }
                canvas.drawBitmap(obj.getBitmap(), src, dst, obj.getPaint());
            } catch (Exception e) {
                list.remove(i);
                i--;
            }
        }
    }

    /**
     * 点赞
     *
     * @param x
     * @param y
     */
    public void showHeartView(float x, float y) {
        mStartX = x;
        mStartY = y;
        if (System.currentTimeMillis() - mStartTime > 50) {
            // 禁止同时显示多个赞
            mStartTime = System.currentTimeMillis();
            Bitmap bitmap = createHeart();
            if (bitmap != null) {
                list.add(new PathObj(bitmap, x, y));
                mFlag = true;
                this.post(mRunnable);
            } else {
                stop();
            }
        }
    }

    public void stop() {
        this.removeCallbacks(mRunnable);
        mFlag = false;
    }

    public void release() {
        stop();
        mContext = null;
    }

    public void add(int count) {
        for (int i = 0; i < count; i++) {
            Message msg = Message.obtain();
            msg.what = 0;
            mHandler.sendMessageDelayed(msg, 80 * i);
        }
    }

    private static Bitmap createBitmapSafely(int width, int height) {
        try {
            return Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_4444);
        } catch (OutOfMemoryError error) {
            error.printStackTrace();
        }
        return null;
    }

    /**
     * 随机路径
     */
    public class PathObj {
        private Paint paint;

        public Path path;
        public PathMeasure pathMeasure;

        public float speed;// 速度
        private final float acceleratedSpeed = 0.05f;// 加速度，目前恒定
        private final float speedMax = 6;

        public int curPos;
        public int length;// 路径总长度
        private float[] p = new float[2];// 坐标点，很重要

        private int time;// 执行的次数
        private int scaleTime = 20;// 放大

        private Rect src;
        private Rect dst;

        private Bitmap bitmap;

        private int bitmapWidth;// 图片宽度
        private int bitmapHeight;// 图片高度

        private int bitmapWidthDst;// 最终放大宽度
        private int bitmapHeightDst;// 最终放大高度

        private int alpha = 255;// 透明度范围 0-255
        private int alphaOffset = 5;// 透明度偏移量

        private int alpha2 = 0;
        private int alphaOffset2 = 4;

        /**
         * 初始化路径
         *
         * @param bitmap 绘制的图片
         */
        public PathObj(Bitmap bitmap, float x1, float y1) {
            this.bitmap = bitmap;
            this.bitmapWidth = bitmap.getWidth();
            this.bitmapHeight = bitmap.getHeight();

            bitmapWidthDst = bitmapWidth;// + bitmapWidth/4;
            bitmapHeightDst = bitmapHeight;// + bitmapHeight/4;

            src = new Rect(0, 0, bitmapWidth, bitmapHeight);
            dst = new Rect(0, 0, bitmapWidthDst / 2, bitmapHeightDst / 2);

            paint = new Paint();
            paint.setAntiAlias(true);

            path = new Path();
            pathMeasure = new PathMeasure();

            int factor = 2;
            int initX = (int) mContext.getResources().getDimension(R.dimen.heart_anim_init_x);
            int initY = (int) mContext.getResources().getDimension(R.dimen.heart_anim_init_y);
            if (x1 != 0) {
                initX = (int) x1;
            }

            int xRand = (int) mContext.getResources().getDimension(R.dimen.heart_anim_bezier_x_rand);
            int animLengthRand = (int) mContext.getResources().getDimension(R.dimen.heart_anim_length_rand);
            int bezierFactor = 6;
            int animLength = (int) mContext.getResources().getDimension(R.dimen.heart_anim_length);
            int xPointFactor = (int) mContext.getResources().getDimension(R.dimen.heart_anim_x_point_factor);
            if (x1 != 0) {
                xPointFactor = (int) (x1 - (int) mContext.getResources().getDimension(R.dimen.heart_anim_x_point_factor_1));
            }
            int x = mRandom.nextInt(xRand);
            int x2 = mRandom.nextInt(xRand);

            int y = getHeight() - initY;
            if (y1 != 0) {
                y = (int) y1;
            }
            int y2 = animLength * factor + mRandom.nextInt(animLengthRand);

            factor = y2 / bezierFactor;

            x = xPointFactor + x;
            x2 = xPointFactor + x2;

            int y3 = y - y2;
            y2 = y - y2 / 2;

            path.moveTo(initX, y);
            path.cubicTo(initX, y - factor, x, y2 + factor, x, y2);
            path.moveTo(x, y2);
            path.cubicTo(x, y2 - factor, x2, y3 + factor, x2, y3);

            pathMeasure.setPath(path, false);
            length = (int) (getMeasuredHeight() - (getBottom() - mStartY));
            speed = mRandom.nextInt(2) + 1f;
            //Log.e("ttt", "length---" + length + "---animLengthRand---" + animLengthRand + "---animLength---" + animLength);
        }

        /**
         * 获取bitmap，用来canvas
         *
         * @return
         */
        public Bitmap getBitmap() {
            return bitmap;
        }

        /**
         * 画笔
         *
         * @return
         */
        public Paint getPaint() {
            return paint;
        }

        /**
         * 获取起始Rect
         *
         * @return
         */
        public Rect getSrcRect() {
            return src;
        }

        /**
         * 获取目标Rect，根据当前点坐标计算Rect，已经加入放大/淡出动画
         *
         * @return
         */
        public Rect getDstRect() {
            curPos += speed;
            if (time < scaleTime) {
                speed = 3;
            } else {
                if (speed <= speedMax) {
                    speed += acceleratedSpeed;
                }
            }

            if (curPos > length) {
                curPos = length;
                return null;
            }

            pathMeasure.getPosTan(curPos, p, null);

            if (time < scaleTime) {
                // 放大动画
                float s = (float) time / scaleTime;
                dst.left = (int) (p[0] - bitmapWidthDst / 4 * s);
                dst.right = (int) (p[0] + bitmapWidthDst / 4 * s);
                dst.top = (int) ((p[1] - bitmapHeightDst / 2 * s));
                dst.bottom = (int) (p[1]);
            } else {
                dst.left = (int) (p[0] - bitmapWidthDst / 4);
                dst.right = (int) (p[0] + bitmapWidthDst / 4);
                dst.top = (int) (p[1] - bitmapHeightDst / 2);
                dst.bottom = (int) (p[1]);
            }
            time++;
            if(type == 0){
                alpha();
            }else{
                alphaYin();
            }
            return dst;
        }

        private int alpha() {
            int offset = length - curPos;
            if (offset < length / 1.5) {
                alpha -= alphaOffset;
                if (alpha < 0) {
                    alpha = 0;
                }
                paint.setAlpha(alpha);
            } else if (offset <= 10) {
                alpha = 0;
                paint.setAlpha(alpha);
            }
            return 0;
        }

        private int alphaYin() {
            int center = length / 2;
            int offset = length - curPos;
            //offset = Math.abs(offset);
            if (offset > center) {
                alpha2 += alphaOffset2;
                if (alpha2 > 255) {
                    alpha2 = 255;
                }
                paint.setAlpha(alpha2);
            } else if (offset < length / 1.5) {
                alpha2 -= alphaOffset;
                if (alpha2 < 0) {
                    alpha2 = 0;
                }
                paint.setAlpha(alpha2);
            } else if (offset <= 10) {
                alpha = 0;
                paint.setAlpha(alpha2);
            } else {
                paint.setAlpha(alpha2);
            }
            return 0;
        }

        public int getAlpha() {
            return alpha;
        }

        /**
         * 获取当前执行次数
         *
         * @return
         */
        public int getTime() {
            return time;
        }
    }

}
